package code

// File is a container of all required components for code generation in the file
type File struct {
	PackageName string
	Imports     []Import
	Structs     Structs
	Interfaces  Interfaces
	Methods     []Method
}

// Import is a model for package imports
type Import struct {
	Name string
	Path string
}

// Structs is a group of Struct model
type Structs []Struct

// ByName return struct with matching name. Another return value shows whether there is a struct
// with that name exists.
func (strs Structs) ByName(name string) (Struct, bool) {
	for _, str := range strs {
		if str.Name == name {
			return str, true
		}
	}
	return Struct{}, false
}

// Struct is a definition of the struct
type Struct struct {
	PackageAlias string
	Name         string
	Fields       StructFields
}

// ReferencedType returns a type variable of this struct
func (str Struct) ReferencedType() Type {
	if str.PackageAlias == "" {
		return SimpleType(str.Name)
	}
	return ExternalType{Name: str.Name, PackageAlias: str.PackageAlias}
}

// StructFields is a group of the StructField model
type StructFields []StructField

// ByName return struct field with matching name
func (fields StructFields) ByName(name string) (StructField, bool) {
	for _, field := range fields {
		if field.Name == name {
			return field, true
		}
	}
	return StructField{}, false
}

// StructField is a definition of the struct field
type StructField struct {
	Name string
	Type Type
	Tags map[string][]string
}

// InterfaceType is a definition of the interface
type InterfaceType struct {
	Name    string
	Methods []Method
}

// Code returns token string in code format
func (intf InterfaceType) Code() string {
	return intf.Name
}

// Interfaces is a group of Interface model
type Interfaces []InterfaceType

// ByName return interface by name Another return value shows whether there is an interface
// with that name exists.
func (intfs Interfaces) ByName(name string) (InterfaceType, bool) {
	for _, intf := range intfs {
		if intf.Name == name {
			return intf, true
		}
	}
	return InterfaceType{}, false
}

// Method is a definition of the method inside the interface
type Method struct {
	Receiver Type
	Name     string
	Comments []string
	Params   []Param
	Returns  []Type
}

// Param is a model of method parameter
type Param struct {
	Name string
	Type Type
}
